import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * 服务器:
 * 1:读取请求并解析
 * 2:根据请求计算响应
 * 3:把响应写回客户端
 */
public class UdpEchoServer {
    private DatagramSocket socket = null;
    //网络编程的前提是操作网卡,操作网卡是通过socket对象来操作的

    public UdpEchoServer(int port) throws SocketException {
        //服务器程序,要在服务器启动的时候,就把端口号确定下来,
        //因为客户端是主动的一方,服务器是被动的一方,客户端要知道服务器在哪,才能"主动的了"
        /**
         * 实际运行的时候,端口号指定的规则:
         * 1)端口号是合法的:1-65535
         * 2)不能和别的进程的端口号冲突
         */

        socket = new DatagramSocket(port);
    }

    public void start() throws  IOException {
        System.out.println("服务器启动!");
        while (true) {
            // 1) 读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            /**
             * 这个PatagramPacket 对象就是一个UDP数据报,包含两个部分
             * 1)报头:通过类的属性来表示的
             * 2)载荷:通过构造方法传递的字符数组,作为持有载荷的空间
             */
            //数组是真正存储数据,持有数据的空间,里面保存了载荷
            //一个DatagramPacket就是一个数据报,但本质上是二进制数据,
            //既然是二进制数据,就可以用字符数据表示
            socket.receive(requestPacket);
            // 为了方便在 java 代码中处理 (尤其是后面进行打印) 可以把上述数据报中的二进制数据, 拿出来, 构造成 String
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            // 2) 根据请求计算响应
            String response = process(request);
            // 3) 把响应写回到客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), 0, response.getBytes().length,
                    requestPacket.getSocketAddress());
            //发送的时候,不光有数据,还要有数据要发给谁
            //由于这是UDP,UDP socket自身没有记录对方的IP,端口号 等信息,但 DatagramPacket requestPacket里有
            //getSocketAddress()方法,返回的对象了 就包含了IP ,端口号
            socket.send(responsePacket);

            System.out.printf("[%s:%d] req=%s, resp=%s\n", requestPacket.getAddress(), requestPacket.getPort(),
                    request, response);
        }
    }

    // 由于当前写的是 "回显服务器"
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
